package cn.keyvalue.ccf.common.http;

import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.math.RandomUtils;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;

public class RequestUtils {
	
	public static String[] userAgentArray = new String[]{
		 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)",
		  "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)",
		  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
		  "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)",
		  "Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1",
		  "Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3",
		  "Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12",
		  "Opera/9.27 (Windows NT 5.2; U; zh-cn)",
		  "Opera/8.0 (Macintosh; PPC Mac OS X; U; en)",
		  "Mozilla/5.0 (Macintosh; PPC Mac OS X; U; en) Opera 8.0",
		  "Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1 Safari/525.13",
		  "Mozilla/5.0 (iPhone; U; CPU like Mac OS X) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419.3",
		  "Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13",
		  "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Navigator/9.0.0.6",
		  "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
		  "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)",
		  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; 360se)",
		  "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; TencentTraveler 4.0; .NET CLR 2.0.50727)"
	};
	
	public static String getRandomUserAgent()
	{
		int random = RandomUtils.nextInt(userAgentArray.length);
		return userAgentArray[random];
	}
	
	
	// 将127.0.0.1形式的IP地址转换成十进制整数，这里没有进行任何错误处理
	public static long ipToLong(String strIp) {
		long[] ip = new long[4];
		// 先找到IP地址字符串中.的位置
		int position1 = strIp.indexOf(".");
		int position2 = strIp.indexOf(".", position1 + 1);
		int position3 = strIp.indexOf(".", position2 + 1);
		// 将每个.之间的字符串转换成整型
		ip[0] = Long.parseLong(strIp.substring(0, position1));
		ip[1] = Long.parseLong(strIp.substring(position1 + 1, position2));
		ip[2] = Long.parseLong(strIp.substring(position2 + 1, position3));
		ip[3] = Long.parseLong(strIp.substring(position3 + 1));
		return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
	}

	// 判断IP是否在IP列表中
	public static boolean ipExist(String ip, List<String> ips) {

		Iterator<String> ite = ips.iterator();
		while (ite.hasNext()) {
			boolean ret = ipExist(ip, ite.next().toString());
			if (ret) {
				return true;
			}
		}

		return false;
	}

	// 判断IP是否在网段中，网段格式为：221.179.186.160/27，也可以是单独IP
	public static boolean ipExist(String ip, String rangeip) {

		if (StringUtils.containsNone(rangeip, "/")) {
			if (StringUtils.equals(ip, rangeip)) {
				return true;
			} else {
				return false;
			}
		} else {
			int yanma = NumberUtils.toInt(StringUtils.substringAfter(rangeip,
					"/"));
			int ipcount = 32 - yanma;
			double rangeCount = Math.pow(2, ipcount) - 2;

			long startip = ipToLong(StringUtils.substringBefore(rangeip, "/"));
			long endip = Math.round(startip + rangeCount);

			long iplong = ipToLong(ip);

			if (iplong >= startip && iplong <= endip) {
				return true;
			} else {
				return false;
			}
		}
	}

	// 获取IP地址
	public static String getIP(HttpServletRequest request) {
		String ipaddress = request.getHeader("X-Forwarded-For");
		if (ipaddress == null || ipaddress.length() == 0
				|| StringUtils.equalsIgnoreCase("unknown", ipaddress)) {
			ipaddress = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ipaddress == null || ipaddress.length() == 0
				|| StringUtils.equalsIgnoreCase("unknown", ipaddress)) {
			ipaddress = request.getHeader("x-forwarded-for");
		}
		if (ipaddress == null || ipaddress.length() == 0
				|| StringUtils.equalsIgnoreCase("unknown", ipaddress)) {
			ipaddress = request.getHeader("Proxy-Client-IP");
		}
		if (ipaddress == null || ipaddress.length() == 0
				|| StringUtils.equalsIgnoreCase("unknown", ipaddress)) {
			ipaddress = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ipaddress == null || ipaddress.length() == 0
				|| StringUtils.equalsIgnoreCase("unknown", ipaddress)) {
			ipaddress = request.getRemoteAddr();
		} else {
			// get first ip 192.168.1.110 from: X-Forwarded-For：192.168.1.110,
			// 192.168.1.120, 192.168.1.130, 192.168.1.100
			String[] ipaddrlist = ipaddress.split(",");
			if (ipaddrlist.length > 1) {
				ipaddress = ipaddrlist[0];
			}
		}
		if (ipaddress.length() >= 128) {
			ipaddress = ipaddress.substring(0, 127);
		}
		return ipaddress;
	}

	public static String getLocalIP() throws UnknownHostException {
		InetAddress inet = InetAddress.getLocalHost();
		return inet.getHostAddress();
	}

	public static String copyUrlToString(String url, int time1, int time2)
			throws Exception {
		GetMethod post = null;
		HttpClient client = new HttpClient();
		InputStream is = null;
		String str = null;
		Exception e = null;

		try {
			post = new GetMethod(url);

			HttpConnectionManagerParams managerParams = client
					.getHttpConnectionManager().getParams();
			
			client.getParams().setParameter(HttpMethodParams.USER_AGENT,
					getRandomUserAgent());
			
			managerParams.setConnectionTimeout(time1);
			managerParams.setSoTimeout(time2);
			int status = client.executeMethod(post);

			if (status == 200) {
				is = post.getResponseBodyAsStream();
				str = IOUtils.toString(is);
			}

		} catch (Exception ee) {

			e = ee;

		} finally {
			IOUtils.closeQuietly(is);
			if (post != null) {
				post.releaseConnection();
			}
			client.getHttpConnectionManager().closeIdleConnections(0);
		}

		if (e != null) {
			throw e;
		}

		return str;
	}

	public static String urlToStr(String url, Cookie cookie, String encode)
			throws Exception {
		GetMethod post = null;
		HttpClient client = new HttpClient();
		InputStream is = null;
		String str = null;
		Exception e = null;

		try {
			post = new GetMethod(url);

			client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
					new DefaultHttpMethodRetryHandler());

			client.getParams().setCookiePolicy(CookiePolicy.RFC_2109);
			
			client.getParams().setParameter(HttpMethodParams.USER_AGENT,
					getRandomUserAgent());
			
			HttpState initialState = new HttpState();
			initialState.addCookie(cookie);
			client.setState(initialState);

			HttpConnectionManagerParams managerParams = client
					.getHttpConnectionManager().getParams();
			managerParams.setConnectionTimeout(10000);
			managerParams.setSoTimeout(10000);
			int status = client.executeMethod(post);

			if (status == 200) {

				is = post.getResponseBodyAsStream();
				str = IOUtils.toString(is, encode);

			}

		} catch (Exception ee) {

			e = ee;

		} finally {
			IOUtils.closeQuietly(is);
			if (post != null) {
				post.releaseConnection();
			}
			client.getHttpConnectionManager().closeIdleConnections(0);
		}

		if (e != null) {
			throw e;
		}

		return str;
	}

	public static String urlToStr(String url, Cookie[] cookie, String encode)
			throws Exception {
		GetMethod post = null;
		HttpClient client = new HttpClient();
		InputStream is = null;
		String str = null;
		Exception e = null;

		try {
			post = new GetMethod(url);

			client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
					new DefaultHttpMethodRetryHandler());

			client.getParams().setCookiePolicy(CookiePolicy.RFC_2109);
			
			client.getParams().setParameter(HttpMethodParams.USER_AGENT,
					getRandomUserAgent());
			
			HttpState initialState = new HttpState();
			initialState.addCookies(cookie);
			client.setState(initialState);

			HttpConnectionManagerParams managerParams = client
					.getHttpConnectionManager().getParams();
			managerParams.setConnectionTimeout(30000);
			managerParams.setSoTimeout(30000);
			int status = client.executeMethod(post);

			if (status == 200) {

				is = post.getResponseBodyAsStream();
				str = IOUtils.toString(is, encode);

			}

		} catch (Exception ee) {

			e = ee;

		} finally {
			IOUtils.closeQuietly(is);
			if (post != null) {
				post.releaseConnection();
			}
			client.getHttpConnectionManager().closeIdleConnections(0);
		}

		if (e != null) {
			throw e;
		}

		return str;
	}

	public static String urlToStr(String url, String encode) throws Exception {
		GetMethod post = null;
		HttpClient client = new HttpClient();
		InputStream is = null;
		String str = null;
		Exception e = null;

		try {
			post = new GetMethod(url);

			client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
					new DefaultHttpMethodRetryHandler());
			
			client.getParams().setParameter(HttpMethodParams.USER_AGENT,
					getRandomUserAgent());
			//client.getParams().setParameter("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; 56flvplayer 1.0)");

			HttpConnectionManagerParams managerParams = client
					.getHttpConnectionManager().getParams();
			managerParams.setConnectionTimeout(30000);
			managerParams.setSoTimeout(30000);
			// managerParams.setParameter("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; 56flvplayer 1.0)");
			int status = client.executeMethod(post);
			
			if (status == 200) {

				is = post.getResponseBodyAsStream();
				str = IOUtils.toString(is, encode);
			}

		} catch (Exception ee) {

			e = ee;

		} finally {
			IOUtils.closeQuietly(is);
			if (post != null) {
				post.releaseConnection();
			}
			client.getHttpConnectionManager().closeIdleConnections(0);
		}

		if (e != null) {
			throw e;
		}

		return str;
	}

	public static String urlToStr(String url, String encode, int time1,
			int time2) throws Exception {
		
		return urlToStr(url, encode, getRandomUserAgent(), time1, time2);
	}

	public static String urlToStr(String url, String encode, String userAgent,
			int time1, int time2) throws Exception {
		GetMethod post = null;
		HttpClient client = new HttpClient();
		InputStream is = null;
		String str = null;
		Exception e = null;

		try {
			post = new GetMethod(url);

			client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
					new DefaultHttpMethodRetryHandler());

			if (StringUtils.isNotEmpty(userAgent)) {
				client.getParams().setParameter(HttpMethodParams.USER_AGENT,
						userAgent);
			}

			HttpConnectionManagerParams managerParams = client
					.getHttpConnectionManager().getParams();
			managerParams.setConnectionTimeout(time1);
			managerParams.setSoTimeout(time2);

			int status = client.executeMethod(post);

			if (status == 200) {

				is = post.getResponseBodyAsStream();
				str = IOUtils.toString(is, encode);
			}
//			if( status != 200 )
//			{
//				System.out.println( IOUtils.toString(is, encode) );
//			}
//			System.out.println( status + "_" + url );

		} catch (Exception ee) {

			//e.printStackTrace();
			e = ee;

		} finally {
			IOUtils.closeQuietly(is);
			if (is != null) {
				is.close();
				is = null;
			}
			if (post != null) {
				post.releaseConnection();
				post = null;
			}
			client.getHttpConnectionManager().closeIdleConnections(0);
		}

		if (e != null) {
			throw e;
		}

		return str;
	}

	public static String urlToStr(String url, String encode, String userAgent)
			throws Exception {
		GetMethod post = null;
		HttpClient client = new HttpClient();
		InputStream is = null;
		String str = null;
		Exception e = null;

		try {
			post = new GetMethod(url);

			client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
					new DefaultHttpMethodRetryHandler());
			// client.getParams().setParameter("User-Agent",userAgent);
			client.getParams().setParameter(HttpMethodParams.USER_AGENT,
					getRandomUserAgent());
			client.getParams().setParameter(
					HttpMethodParams.HTTP_CONTENT_CHARSET, encode);
			// client.getParams().setParameter(HttpMethodParams.USER_AGENT,userAgent);

			HttpConnectionManagerParams managerParams = client
					.getHttpConnectionManager().getParams();
			managerParams.setConnectionTimeout(30000);
			managerParams.setSoTimeout(30000);
			// managerParams.setParameter("User-Agent",userAgent);
			int status = client.executeMethod(post);

			if (status == 200) {

				is = post.getResponseBodyAsStream();
				str = IOUtils.toString(is, encode);
			}

		} catch (Exception ee) {

			e = ee;

		} finally {
			IOUtils.closeQuietly(is);
			if (post != null) {
				post.releaseConnection();
			}
			client.getHttpConnectionManager().closeIdleConnections(0);
		}

		if (e != null) {
			throw e;
		}

		return str;
	}

	public static String urlToStr(String url, String encode, Properties pro)
			throws Exception {
		PostMethod post = null;
		HttpClient client = new HttpClient();
		InputStream is = null;
		String str = null;
		Exception e = null;

		try {
			post = new PostMethod(url);

			Iterator<Object> ite = pro.keySet().iterator();
			while (ite.hasNext()) {
				String key = ite.next().toString();
				post.addParameter(key, pro.getProperty(key));
			}

			client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
					new DefaultHttpMethodRetryHandler());
			// client.getParams().setParameter("User-Agent",userAgent);
			client.getParams().setParameter(HttpMethodParams.USER_AGENT,
					getRandomUserAgent());
			client.getParams().setParameter(
					HttpMethodParams.HTTP_CONTENT_CHARSET, encode);
			// client.getParams().setParameter(HttpMethodParams.USER_AGENT,userAgent);

			HttpConnectionManagerParams managerParams = client
					.getHttpConnectionManager().getParams();
			managerParams.setConnectionTimeout(30000);
			managerParams.setSoTimeout(30000);
			// managerParams.setParameter("User-Agent",userAgent);
			int status = client.executeMethod(post);

			//System.out.println( status );
			
			if (status == 200) {

				is = post.getResponseBodyAsStream();
				str = IOUtils.toString(is, encode);
			}

		} catch (Exception ee) {

			ee.printStackTrace();
			e = ee;

		} finally {
			IOUtils.closeQuietly(is);
			if (post != null) {
				post.releaseConnection();
			}
			client.getHttpConnectionManager().closeIdleConnections(0);
		}

		if (e != null) {
			throw e;
		}

		return str;
	}

	public static String getCookieValue(HttpServletRequest request, String name) {
		javax.servlet.http.Cookie[] cookies = request.getCookies();

		if (cookies != null) {
			for (int i = 0; i < cookies.length; i++) {
				if (StringUtils.equalsIgnoreCase(cookies[i].getName(), name)) {
					return cookies[i].getValue();
				}
			}
		}

		return null;
	}

	public static void main(String[] args) throws Exception {
		String url = "http://www.leiphone.com";
		System.out.println(urlToStr(url, "utf-8",5000,5000));
	}

}
